package com.bw.lib_miv

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.bw.lib_net.BaseRes
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

abstract class BaseViewModel<iuiIntent : IUiIntent, iuiState : IUiState<Any>> : ViewModel() {
    private val _uiIntent = Channel<iuiIntent>(Channel.UNLIMITED)
    private val _uiState = MutableStateFlow<IUiState<Any>>(IUiState.OnLodging)
    val uiState: StateFlow<IUiState<Any>>
        get() = _uiState

    init {
        viewModelScope.launch {
            _uiIntent.consumeAsFlow().collect {
                handlerIntent(it)
            }
        }
    }

    //处理意图
    abstract fun handlerIntent(intent: iuiIntent)

    //发送意图
    fun sendIntent(intent: iuiIntent) {
        viewModelScope.launch {
            _uiIntent.send(intent)
        }
    }

    //发送状态
    fun sendState(state: (IUiState<Any>) -> IUiState<Any>) {
        viewModelScope.launch {
            _uiState.update { state(_uiState.value) }
        }
    }

    //网络请求
    fun <T> httpRequest(request: Flow<BaseRes<T>>, type: RequestType = RequestType.DEFAULT) {
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch { catch ->
                    Log.d("TagA", "httpRequest: ${catch.message}")
                    catch.printStackTrace()
                    sendState { catch?.message?.let { IUiState.OnFailed(it) } as iuiState }
                }
                .collect { resp ->
                    Log.d("TagA", "code: ${resp.code}")
                    if (resp.code == 0) {
                        sendState { IUiState.OnSuccess(resp.data, type) as iuiState }
                    } else {
                        sendState { resp.msg?.let { IUiState.OnFailed(it) } as iuiState }
                    }
                }
        }
    }
}